// 浏览器环境 非严格模式
function getGlobalObject() {
    return this;
}
Function.prototype.applyFn = function apply(thisArg, argsArray) { // `apply` 方法的 `length` 属性是 `2`。
    // 1.如果 `IsCallable(func)` 是 `false`, 则抛出一个 `TypeError` 异常。
    if (typeof this !== 'function') {
        throw new TypeError(this + ' is not a function');
    }
    // 2.如果 argArray 是 null 或 undefined, 则
    // 返回提供 thisArg 作为 this 值并以空参数列表调用 func 的 [[Call]] 内部方法的结果。
    if (typeof argsArray === 'undefined' || argsArray === null) {
        argsArray = [];
    }

    // 3.如果 Type(argArray) 不是 Object, 则抛出一个 TypeError 异常 .
    if (argsArray !== new Object(argsArray)) {
        throw new TypeError('CreateListFromArrayLike called on non-object');
    }
    if (typeof thisArg === 'undefined' || thisArg === null) {
        // 在外面传入的 thisArg 值会修改并成为 this 值。
        // ES3: thisArg 是 undefined 或 null 时它会被替换成全局对象 浏览器里是window
        thisArg = getGlobalObject();
    }
    // ES3: 所有其他值会被应用 ToObject 并将结果作为 this 值，这是第三版引入的更改。
    thisArg = new Object(thisArg);
    var __fn = '__fn';
    thisArg[__fn] = this;
    // 9.提供 thisArg 作为 this 值并以 argList 作为参数列表，调用 func 的 [[Call]] 内部方法，返回结果
    var result = thisArg[__fn](...argsArray);
    delete thisArg[__fn];
    return result;
};

function getName() {
    console.log(this.name)
}

getName.applyFn({ name: '123' })